package com.xpec.c4.service.module.async;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.xpec.c4.service.module.BasicServiceModule;
import com.xpec.c4.service.module.task.TaskAsyncCommand;

/**
 * 異步處理管理器 
 * @author yangbingyan
 *
 */
public class AsyncProcedureManager {
	/** log4j object */
	private static final Log log = LogFactory.getLog(AsyncProcedureManager.class);
	
	/**
	 * 命令處理完畢後需要回調的模塊
	 */
	private BasicServiceModule basicServiceModule;
	
	/**
	 * 異步命令處理程序列表
	 */
	private List<AsyncCommandProcedure> asyncCommandProcedureList;

	/**
	 * 默認的處理線程數量
	 */
	private static final int defaultProcedureCount = 1;
	
	/**
	 * 建立幾條線程來處理異步命令
	 */
	private int procedureCount = defaultProcedureCount;
	
	/**
	 * 當前線程的索引, 將命令分配到不同線程時使用
	 */
	private int curIdx = 0;
	
	/**
	 * 
	 * @param basicServiceModule
	 */
	public AsyncProcedureManager(BasicServiceModule basicServiceModule){
		this.basicServiceModule = basicServiceModule;
	}
	
	/**
	 * 建立異步命令處理程序, 無參數默認建立1條
	 */
//	public void createAsyncProcedure(){
//		createAsyncProcedure(procedureCount);
//	}
	
	/**
	 * 建立異步命令處理程序
	 * @param count
	 */
	public void createAsyncProcedure(boolean useRecordedQueue){
		
		if(asyncCommandProcedureList != null){
			// log
		}
		
		asyncCommandProcedureList = new ArrayList<AsyncCommandProcedure>();
		
		for(int i = 0; i < procedureCount ; i++){
			asyncCommandProcedureList.add(new AsyncCommandProcedure(i, basicServiceModule, useRecordedQueue));
		}		
	}
	
	/**
	 * 
	 * @return
	 */
	public boolean startup(){
		
		if(asyncCommandProcedureList == null){
			return false;
		}
	
		boolean result = true;
		for(AsyncCommandProcedure it: asyncCommandProcedureList){
			result &= it.startup();
		}
		return result;
	}
	
	/**
	 * 
	 * @return
	 */
	public int getCurrentTaskCount(){
		int cnt = 0;
		for(AsyncCommandProcedure it: asyncCommandProcedureList){
			cnt += it.getQueueSize();
		}
		return cnt;
	}
	
	/**
	 * 
	 * @return
	 */
	public boolean shutdown(){
		
		if(asyncCommandProcedureList == null){
			return true;
		}
	
		for(AsyncCommandProcedure it: asyncCommandProcedureList){
			it.shutdown();
			if(!it.isTerminated())
			{
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		return true;
	}	

	/**
	 * 
	 * @param obj
	 * @return
	 */
	public boolean addAsyncCommand(TaskAsyncCommand obj){
		
		if(obj == null || asyncCommandProcedureList == null){
			return false;
		}
		// 指定使用某個queue
		int idx = obj.getQueueID();
		if(idx < 0 || idx >= procedureCount){
				// 超過queue數量就使用第一個
				idx = 0;
		}

		//System.out.println("********[addAsyncCommand] taskQueue ="+idx + " totalCount =" +procedureCount+" Class = " + obj.getClass().toString());
		
		// BM test 暫時不顯示 task count log
		/*
		// queue 裡工作消化不完的警示
		AsyncCommandProcedure procedure = asyncCommandProcedureList.get(idx);
		if (procedure.getQueueSize() >= 50) {
			if (procedure.getQueueSize() % 50 == 0) {
				if (log.isErrorEnabled()) {
					log.error("AsyncCommandProcedure[" + idx + "] task count reach " + procedure.getQueueSize());
				}
			}
		}
		*/

		obj.setModuleServer(basicServiceModule);
		if(procedureCount == 1){
			return asyncCommandProcedureList.get(0).addAsyncCommand(obj);
		}
		else
		{
			return asyncCommandProcedureList.get(idx).addAsyncCommand(obj);
		}
	}

	public int getProcedureCount() {
		return procedureCount;
	}

	public void setProcedureCount(int procedureCount) {
		this.procedureCount = procedureCount;
	}
	
	public int getTaskQueueSize()
	{
		if(asyncCommandProcedureList == null) return 0;
		int result = 0;
		for(AsyncCommandProcedure it: asyncCommandProcedureList)
		{
			result += it.getQueueSize();
		}		
		return result;
	}
	
	public Map<Class, AtomicInteger> getFirstAsyncQueueCounter()
	{
		return this.asyncCommandProcedureList.get(0).getCountingMap();
	}
}
